package com.gang.mars.redisson.lock;

import lombok.SneakyThrows;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * 学习参考 周瑜 https://www.bilibili.com/video/BV1D54y1H7Bh?p=2&spm_id_from=pageDriver
 *
 * 一把简单的锁
 *
 * */

public class GangReentrantLock implements Lock {

    private volatile int state;

    private static final Unsafe unsafe = getUnsafe();

    /**
     * 偏移量
     * */
    private static long stateOffset;

    static
    {
        try
        {
           stateOffset = unsafe.objectFieldOffset(GangReentrantLock.class.getDeclaredField("state"));
        } catch (NoSuchFieldException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void lock() {

        //被第一个调用线程暂用，获取锁成功
        //state = 1;

        /**
         * 共5个参数
         * @Param Object o,GangReentrantLock类
         * @Param long offset,偏移量类GangReentrantLock中,定义的属性state值
         * @Param int expected,类GangReentrantLock属性state初始值
         * @Param int x,类GangReentrantLock属性state更新值
         *
         * 业务意义
         * 第一个线程执行CAS，0 修改 1，返回成功，取锁成功，执行业务功能
         * 第二个线程执行CAS，0 修改 1，返回失败，取锁失败，进入等待状态
         * 第三线程二会不停修改CAS，直到成功将0 修改 1，取锁成功，执行业务功能
         *
         * 其余线程依次执行
         * */
        //boolean b = unsafe.compareAndSwapInt(this, stateOffset, 0, 1);
        /**
         * 线程阻塞
         * */
        while (!unsafe.compareAndSwapInt(this, stateOffset, 0, 1)){
            /**
             * 业务意义,等待获取锁
             * 问题，一直不停循环会过大消耗CUP
             * */
            System.out.println("线程: " + Thread.currentThread().getName()+ " 正在加锁");

            /**
             * 公平锁
             * 语意，先到的线程先加锁
             * 思路
             * 线程1，先到获取锁
             * 线程2，次到循环
             * 线程3，后到，如果参与循环，则不公平；排队park()
             * */
        }

        /**
         * 业务意义,已经取到锁
         * */
        System.out.println("线程: " + Thread.currentThread().getName() +" 已取到锁");


    }

    @Override
    public void unlock() {
        state = 0;

    }

    @SneakyThrows
    private static Unsafe getUnsafe(){
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        Unsafe unsafe = (Unsafe) field.get(null);
        return unsafe;
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        //TODO
    }

    @Override
    public boolean tryLock() {
        //TODO
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        //TODO
        return false;
    }



    @Override
    public Condition newCondition() {
        //TODO
        return null;
    }
}
